package com.wt.springsamples.juc;

import com.wt.springsamples.juc.atguigu.A;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * ThreadPoolExecutor原理:
 *  1、当添加的任务数量小于核心线程数量时：
 *   每添加一个任务（调用execute方法），都会创建一个线程处理改任务，任务执行完成后在任务队列（workQueue）上阻塞，
 *   直到有新的任务加入到队列，getTask()方法循环监听队列，Work类->runWorker方法->while循环->getTask()方法，所以，线程池中活跃的线程数量始终为核心线程数；
 *  2、当添加的任务数量超过核心线程数量时，会将任务添加到队列中，此时有corePoolSize个线程处理队列中的任务，
 *  3、当向队列中添加数据失败（队列已满），创建新的线程处理新加入的任务，完成后同核心线程一起处理队列中的任务，工作线程数量达到最大线程数量时创建线程失败，执行拒绝策略
 *  4、默认情况下,当超过核心线程数量时，新创建的线程存在过期时间（keepAliveTime参数指定），并从任务队列中获取任务进行消费,
 *  若keepAliveTime指定的时间内没有获取到任务，则退出runWorker的while循环，执行processWorkerExit方法完成新创建线程的
 *  销毁（调用当前工作线程的interrupt方法终止线程，工作线程数量递减，从线程集合中移除等）
 *  5、核心线程也可以指定过期时间(设置allowCoreThreadTimeOut参数为true)，指定后销毁过程同普通线程（步骤四）
 */


public class ExecutorTest {

    volatile int no;

    public static void main(String[] args) {
        //volatile int no =0;//编译错误，
//        A a = new A();
//        A b = new A();
//        a.start();
//        b.start();
        ThreadPoolExecutor executorService  = new ThreadPoolExecutor(8, 16,0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(1000));
        executorService.setRejectedExecutionHandler(new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                executor.submit(r);
            }
        });
//        executorService.setRejectedExecutionHandler(new MyRejectedExecutionHandler());
////        executorService.execute(new NumberRunnable(1));
        for(int i=0;i<10;i++){
            executorService.execute(new A());
        }
    }
}
